package cn.pugle.base.reflect.proxy;

import org.springframework.core.MethodIntrospector;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

import cn.pugle.quartz.cluster.annotation.QuartzScheduled;

/**
 * Created by tzp on 16-11-29.
 */
public class JDKDynamicProxyTest {
    public static void main(String[] args) throws NoSuchMethodException {
        //原来的对象
        TargetClass target = new TargetClass();
        Map<Method, QuartzScheduled> annotatedMethods = MethodIntrospector.selectMethods(target.getClass(),
                new MethodIntrospector.MetadataLookup<QuartzScheduled>() {
                    @Override
                    public QuartzScheduled inspect(Method method) {
                        return AnnotationUtils.getAnnotation(method, QuartzScheduled.class);
                    }
                });

        //代理后的对象
        TargetInterface proxyInstance = (TargetInterface) Proxy.newProxyInstance(TargetClass.class.getClassLoader(),
                TargetClass.class.getInterfaces(), new MyProxyInvocationHandler(target));
        proxyInstance.myMethod();

        for (Map.Entry<Method, QuartzScheduled> entry : annotatedMethods.entrySet()) {
            Method myMethod = entry.getKey();
            QuartzScheduled scheduled = entry.getValue();


            Method methodInProxy = proxyInstance.getClass().getMethod(myMethod.getName(), myMethod.getParameterTypes());
            System.out.println(myMethod == methodInProxy);
        }
    }
}


class MyProxyInvocationHandler implements InvocationHandler {
    Object target;

    public MyProxyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy running");
//        System.out.println(proxy.getClass());// proxy is instanceof Proxy
        Object result = method.invoke(target, args);
        return result;
    }
}


